package com.zlx.store.order.controller;

import com.zlx.store.common.annotation.SecurityAnno;
import com.zlx.store.common.constant.RespCode;
import com.zlx.store.common.constant.SecurityConstant;
import com.zlx.store.common.exception.ShoppingCartEmptyException;
import com.zlx.store.common.results.HttpResp;
import com.zlx.store.common.util.StringTool;
import com.zlx.store.domain.entity.Coupon;
import com.zlx.store.domain.entity.CouponRelateUser;
import com.zlx.store.domain.entity.Goods;
import com.zlx.store.domain.entity.vo.GoodsVO;
import com.zlx.store.domain.entity.vo.OrderVO;
import com.zlx.store.domain.entity.vo.ShoppingCartVO;
import com.zlx.store.domain.entity.vo.TokenVO;
import com.zlx.store.order.service.Impl.OrderServiceImpl;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("api/order")
public class OrderController {
    @Autowired
    private OrderServiceImpl orderService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 从redis中读取token的方法
     *
     * @param request
     * @return
     */
    private TokenVO getTokenVo(HttpServletRequest request) {
        String token = request.getHeader("token");
        return (TokenVO) redisTemplate.opsForValue().get(token);
    }

    @ApiOperation(notes = "管理员寻找所有订单", value = "findAll")
    @ApiImplicitParam()
    @SecurityAnno(roleName = SecurityConstant.USER_ROLE_ADMIN)
    @GetMapping("findAll")
    public HttpResp findAll(HttpServletRequest request) {
        TokenVO tokenVo = getTokenVo(request);
        List<OrderVO> all = orderService.find(null, null);
        return HttpResp.httpResp(RespCode.ORDER_OPERATION_SUCCESS, all, new Date());
    }

    @ApiOperation(notes = "经理寻找自己的店铺订单", value = "findOrderByManager")
    @ApiImplicitParam()
    @SecurityAnno(roleName = SecurityConstant.USER_ROLE_MANAGER)
    @GetMapping("findOrderByManager")
    public HttpResp findOrderByManager(HttpServletRequest request, Long storeId) {
        TokenVO tokenVO = getTokenVo(request);
        if (tokenVO.getStoreIds().stream().anyMatch(aLong -> aLong.equals(storeId))) {
            List<OrderVO> all = orderService.find(storeId, null);
            return HttpResp.httpResp(RespCode.ORDER_OPERATION_SUCCESS, all, new Date());
        }
        return HttpResp.httpResp(RespCode.ORDER_OPERATION_DENY, "无查看该店铺权限", new Date());


    }

    @ApiOperation(notes = "用户查找自己购买过的订单", value = "findOrderByCustomer")
    @ApiImplicitParam()
    @SecurityAnno(roleName = SecurityConstant.USER_ROLE_CUSTOMER)
    @GetMapping("findOrderByCustomer")
    public HttpResp findOrderByCustomer(HttpServletRequest request) {
        TokenVO tokenVo = getTokenVo(request);
        List<OrderVO> all = orderService.find(null, tokenVo.getUserId());
        return HttpResp.httpResp(RespCode.ORDER_OPERATION_SUCCESS, all, new Date());
    }

    /**
     * 创建待付款订单，一旦订单超过半小时未付款，订单将从redis中被删除（设置过期时间为半小时）
     * 所以用户是不能自己手动删除订单的（模仿淘宝，只有一个付款过期时间，但就是没有取消订单的选项）
     *
     * @param request
     * @return
     */
    @SecurityAnno(roleName = SecurityConstant.USER_ROLE_CUSTOMER)
    @PostMapping("createOrder")
    @ApiOperation(notes = "用户使用购物车或者直接购买创建订单", value = "createOrder")
    @ApiImplicitParam()
    public HttpResp createOrder(HttpServletRequest request, ShoppingCartVO shoppingCartVO, Coupon coupon, GoodsVO goodsVO,HttpServletResponse response) throws ShoppingCartEmptyException {
        TokenVO tokenVO = getTokenVo(request);
        ShoppingCartVO cartVO = (ShoppingCartVO) redisTemplate.opsForValue().get("shoppingCart" + tokenVO.getUserId());
//思考之一是，自定义异常其实成为了逻辑处理的一部分，这样是否增加了耦合性，即异常与逻辑处理之间的关系变得模糊了；
        if (!Objects.isNull(goodsVO)) {
            List<GoodsVO> goodsVOList = shoppingCartVO.getGoodsVOList();
            goodsVOList.add(goodsVO);
        }
        if (Objects.isNull(shoppingCartVO) || Objects.isNull(cartVO)) {
            throw new ShoppingCartEmptyException("购物车为空");
        }
        if (cartVO.equals(shoppingCartVO)) {
            orderService.insert(cartVO, tokenVO, coupon,response);
        } else orderService.insert(shoppingCartVO, tokenVO, coupon,response);
        Object o = redisTemplate.opsForValue().get("PayOrder" + tokenVO.getUserId());
        return HttpResp.httpResp(RespCode.ORDER_OPERATION_SUCCESS, (List<OrderVO>) o, new Date());
    }

    /**
     * 查找未付款订单
     *
     * @param request
     * @return
     */
    @ApiOperation(notes = "用户查找自己未付款的订单", value = "findPayOrderByCustomer")
    @ApiImplicitParam()
    @SecurityAnno(roleName = SecurityConstant.USER_ROLE_CUSTOMER)
    @GetMapping("findPayOrderByCustomer")
    public HttpResp findPayOrderByCustomer(HttpServletRequest request, HttpServletResponse response) {
        TokenVO tokenVo = getTokenVo(request);
        Object o = redisTemplate.opsForValue().get("PayOrder" + tokenVo.getUserId());
        if (StringTool.isNull(o)) return HttpResp.httpResp(RespCode.ORDER_OPERATION_SUCCESS, null, new Date());
        Long expire = redisTemplate.opsForValue().getOperations().getExpire("PayOrder" + tokenVo.getUserId());
        Instant instant = Instant.ofEpochMilli(expire);
        Date expiration = Date.from(Instant.from(LocalDateTime.ofInstant(instant, ZoneId.systemDefault())));
        return HttpResp.httpResp(RespCode.ORDER_OPERATION_SUCCESS, (List<OrderVO>) o, expiration);
    }
}
